// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

#include "magna/tester.h"

/*
    Программа, генерирующая проверочные данные для `encoding_ansi_1`:

    ```csharp
    using System;

    public static void Main()
    {
        var text = "У попа была собака, он её любил";

        RegisterRequiredProviders();
        ShowEncoding (Encoding.GetEncoding (1251), text);
    }

    public static void ShowEncoding
        (
            Encoding encoding,
            string text
        )
    {
        var bytes = encoding.GetBytes (text);

        Console.Write ("const am_byte source[] = { ");
        foreach (var b in bytes) {
            Console.Write ("0x{0:X2}, ", b);
        }
        Console.WriteLine ("0x00 };");

        Console.Write ("const unsigned int destination[] = { ");
        foreach (var c in text) {
            Console.Write ("0x{0:X4}, ", (uint)c);
        }
        Console.WriteLine ("0x0000 };");
    }

    public static void RegisterRequiredProviders()
    {
        Encoding.RegisterProvider (CodePagesEncodingProvider.Instance);
    }
    ```

 */

TESTER(encoding_ansi_1)
{
    const Encoding *ansi = encoding_ansi();
    const am_byte source[] = { 0xD3, 0x20, 0xEF, 0xEE, 0xEF, 0xE0,
        0x20, 0xE1, 0xFB, 0xEB, 0xE0, 0x20, 0xF1, 0xEE, 0xE1, 0xE0,
        0xEA, 0xE0, 0x2C, 0x20, 0xEE, 0xED, 0x20, 0xE5, 0xB8, 0x20,
        0xEB, 0xFE, 0xE1, 0xE8, 0xEB, 0x00 };
    const am_byte *p1;
    const unsigned int destination[] = { 0x0423, 0x0020, 0x043F, 0x043E,
        0x043F, 0x0430, 0x0020, 0x0431, 0x044B, 0x043B, 0x0430, 0x0020,
        0x0441, 0x043E, 0x0431, 0x0430, 0x043A, 0x0430, 0x002C, 0x0020,
        0x043E, 0x043D, 0x0020, 0x0435, 0x0451, 0x0020, 0x043B, 0x044E,
        0x0431, 0x0438, 0x043B, 0x0000 };
    const unsigned int *p2;

    CHECK (ansi != NULL);
    CHECK (ansi->name != NULL);
    CHECK (sizeof (source) == sizeof (destination) / sizeof (destination[0]));

    for (p1 = source, p2 = destination; *p1; ++p1, ++p2) {
        CHECK (ansi->char_to_unicode (*p1) == *p2);
        CHECK (ansi->unicode_to_char (*p2) == *p1);
    }
}

TESTER(ansi2utf_1)
{
    const Encoding *ansi = encoding_ansi();
    const am_byte source[] = { 0xD3, 0x20, 0xEF, 0xEE, 0xEF, 0xE0,
        0x20, 0xE1, 0xFB, 0xEB, 0xE0, 0x20, 0xF1, 0xEE, 0xE1, 0xE0,
        0xEA, 0xE0, 0x2C, 0x20, 0xEE, 0xED, 0x20, 0xE5, 0xB8, 0x20,
        0xEB, 0xFE, 0xE1, 0xE8, 0xEB, 0x00 };
    const am_byte destination[] = { 0xD0, 0xA3, 0x20, 0xD0, 0xBF, 0xD0,
        0xBE, 0xD0, 0xBF, 0xD0, 0xB0, 0x20, 0xD0, 0xB1, 0xD1, 0x8B, 0xD0,
        0xBB, 0xD0, 0xB0, 0x20, 0xD1, 0x81, 0xD0, 0xBE, 0xD0, 0xB1, 0xD0,
        0xB0, 0xD0, 0xBA, 0xD0, 0xB0, 0x2C, 0x20, 0xD0, 0xBE, 0xD0, 0xBD,
        0x20, 0xD0, 0xB5, 0xD1, 0x91, 0x20, 0xD0, 0xBB, 0xD1, 0x8E, 0xD0,
        0xB1, 0xD0, 0xB8, 0xD0, 0xBB, 0x00 };
    Buffer output = BUFFER_INIT;
    Span input = span_init (source, sizeof (source));
    Span ethalon = span_init (destination, sizeof (destination));

    CHECK (ansi != NULL);
    CHECK (ansi->name != NULL);

    CHECK (ansi2utf (&output, input));
    CHECK (buffer_position (&output) == sizeof (destination));
    CHECK (buffer_compare_span (&output, ethalon) == 0);

    buffer_destroy (&output);
}

TESTER(utf2ansi_1)
{
    const Encoding *ansi = encoding_ansi();
    const am_byte source[] = { 0xD0, 0xA3, 0x20, 0xD0, 0xBF, 0xD0,
        0xBE, 0xD0, 0xBF, 0xD0, 0xB0, 0x20, 0xD0, 0xB1, 0xD1, 0x8B, 0xD0,
        0xBB, 0xD0, 0xB0, 0x20, 0xD1, 0x81, 0xD0, 0xBE, 0xD0, 0xB1, 0xD0,
        0xB0, 0xD0, 0xBA, 0xD0, 0xB0, 0x2C, 0x20, 0xD0, 0xBE, 0xD0, 0xBD,
        0x20, 0xD0, 0xB5, 0xD1, 0x91, 0x20, 0xD0, 0xBB, 0xD1, 0x8E, 0xD0,
        0xB1, 0xD0, 0xB8, 0xD0, 0xBB, 0x00 };
    const am_byte destination[] = { 0xD3, 0x20, 0xEF, 0xEE, 0xEF, 0xE0,
        0x20, 0xE1, 0xFB, 0xEB, 0xE0, 0x20, 0xF1, 0xEE, 0xE1, 0xE0,
        0xEA, 0xE0, 0x2C, 0x20, 0xEE, 0xED, 0x20, 0xE5, 0xB8, 0x20,
        0xEB, 0xFE, 0xE1, 0xE8, 0xEB, 0x00 };
    Buffer output = BUFFER_INIT;
    Span input = span_init (source, sizeof (source));
    Span ethalon = span_init (destination, sizeof (destination));

    CHECK (ansi != NULL);
    CHECK (ansi->name != NULL);

    CHECK (utf2ansi (&output, input));
    CHECK (buffer_position (&output) == sizeof (destination));
    CHECK (buffer_compare_span (&output, ethalon) == 0);

    buffer_destroy (&output);
}
